import java.util.Iterator;
import java.util.LinkedList;
import java.util.NoSuchElementException;
import java.util.concurrent.Semaphore;


/**
 * @author Daniel Bruzual
 * @author Sabrina Fernandez
 * @author Manuel Gomez
 * @author Marilyn Nowacka
 */
public class EjecutadorInstrucciones extends Thread {
	//instrucciones por ejecutar
	private LinkedList<Instruccion> instrucciones;
	
	/*hace la conversion de direccion virtual a real y lleva el
	control de los marcos de pagina */
	private ManejadorInstruccion manejadorIns;
	
	//Para acceder a la lista de instrucciones, o a la memoria
	private Semaphore mutex;
	
	//indica si solo se debe ejecutar una instruccion (step)
	public boolean executeAndStop;

	public EjecutadorInstrucciones(	LinkedList<Instruccion> ins, ManejadorInstruccion man, Semaphore mt){
		this.instrucciones = ins;
		this.manejadorIns = man;
		executeAndStop = true;
		this.mutex = mt;
	}
	
	public void start(){
		super.start();
	}
	
	public void run(){
		Instruccion instru;
		
		//estar siempre preparado para recibir nuevas instrucciones
		while(true){
			
		while(!instrucciones.isEmpty()){
			try{
				mutex.acquire();
				instru = instrucciones.poll();
				mutex.release();
				
				//ejecutar la instruccion				
				System.out.println("Instrucción: "+instru);
				int hits_antes = manejadorIns.getHits();
				int pos = manejadorIns.ejecutaInstruccion(instru);
				int hits_despues = manejadorIns.getHits();
				if(hits_despues > hits_antes){
					System.out.println("Hit. La página está en el marco "+pos*4+"Kb.");
				} else {
					System.out.println("Miss. Trayendo la página al marco "+pos*4+"Kb.");
				}
				
				if(executeAndStop){
					//estamos en modo step, solo se debe ejecutar una instruccion
					//se duerme hasta que se le notifique que debe ejecutar otra instruccion
					this.suspend();
				} else {
					//domir por la duracion de la instruccion y luego proseguir a ejecutar la
					//siguiente
					try{
						this.sleep(instru.getDelay());
					} catch (InterruptedException e){
					//no hacer nada, solo se debe ejecutar la sig. instruccion
					}
				}
			} catch (InterruptedException e){
				
			}
		}
		
		}
		
	}
}
